This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

dates <- ymd('2020-01-01') + weeks(0:53)
countries <- unlist(countries_per_continent) %>% sort()

base_df <- tibble(
    date = rep(dates, rep(length(countries), length(dates))),
    location = rep(countries, length(dates))
) %>%
    filter(year(date) == 2020) %>%
    mutate(week = week(date)) %>%
    select(week, location) %>%
    left_join(covid_data %>% select(location, continent, population) %>% distinct(),
              by = 'location') %>%
    drop_na()

df <- covid_data %>%
    filter(lubridate::year(date) == 2020) %>%
    replace_na(list(new_cases = 0,
                    new_deaths = 0,
                    new_tests = 0)) %>%
    group_by(week = week(date),
             location, continent, population) %>%
    summarise(new_cases = sum(new_cases),
              positive_rate = round(sum(new_cases) / sum(new_tests), 2),
              new_deaths = sum(new_deaths),
              .groups = 'drop')

evolution <- base_df %>%
    left_join(df, by = c('week', 'location')) %>%
    select(week,
           location,
           continent = continent.x,
           population = population.x,
           new_cases,
           positive_rate,
           new_deaths) %>%
    replace_na(list(new_cases = 0,
                    positive_rate = 0,
                    new_deaths = 0)) %>%
    group_by(location, continent, population) %>%
    mutate(positive_rate = if_else(is.infinite(positive_rate), 0, positive_rate),
           total_deaths = slide_dbl(new_deaths, sum, .before = Inf, .after = 0, .complete = FALSE),
           total_cases = slide_dbl(new_cases, sum,.before = Inf, .after = 0, .complete = FALSE),
           cases_pm = round(total_cases / population * 1e+6),
           deaths_pm = round(total_deaths / population * 1e+6)) %>% 
    ungroup()



evolution %>%
    plot_ly(x         = ~ deaths_pm,
            y         = ~ cases_pm,
            color     = ~ continent,
            size      = ~ population,
            hoverinfo = 'text',
            text      = ~ location) %>%
    add_text(x = 45,
             y = 500,
             text = ~ paste0('week: ', week),
             frame = ~ week,
             textfont = list(size = 150,
                             color = toRGB('gray80'),
                             opacity = .5),
             showlegend = FALSE) %>%
    add_markers(frame  = ~ week,
                ids    = ~ location,
                marker = list(showmode = 'diameter',
                              showref = 0.9)) %>%
    layout(xaxis = list(type = 'log',
                        range = c(0, 3.25),
                        title = 'Total Deaths per Million'),
           yaxis = list(title = 'Total Cases per Million',
                        type = 'log',
                        range = c(0, 5.1)),
           title = 'Total Cases & Total Deaths per Million') %>%
    animation_opts(frame      = 500,
                   transition = 500) %>%
    animation_slider(hide = TRUE)
week_new_cases <- evolution %>% 
    select(week, location, new_cases) %>% 
    mutate(new_cases_week = paste0('new_cases_week_', week)) %>% 
    select(- week) %>% 
    spread(new_cases_week, new_cases, fill = 0) %>% 
    arrange(location)

week_positive_rate <- evolution %>% 
    select(week, location, positive_rate) %>% 
    mutate(positive_rate_week = paste0('positive_rate_week_', week)) %>% 
    select(- week) %>% 
    spread(positive_rate_week, positive_rate, fill = 0) %>% 
    arrange(location)

week_new_deaths <- evolution %>% 
    select(week, location, new_deaths) %>% 
    mutate(new_deaths_week = paste0('new_deaths_week_', week)) %>% 
    select(- week) %>% 
    spread(new_deaths_week, new_deaths, fill = 0) %>% 
    arrange(location)


cd_tidy <- week_new_cases %>% 
    bind_cols(week_positive_rate %>% select(-location)) %>% 
    bind_cols(week_new_deaths %>% select(-location))

cd_tidy
require(embed)
Loading required package: embed
Loading required package: recipes

Attaching package: 㤼㸱recipes㤼㸲

The following object is masked from 㤼㸱package:stringr㤼㸲:

    fixed

The following object is masked from 㤼㸱package:stats㤼㸲:

    step
require(tidymodels)
Loading required package: tidymodels
-- Attaching packages ---------------------------------------------------------- tidymodels 0.1.2 --
v broom     0.7.5     v rsample   0.0.9
v dials     0.0.9     v tune      0.1.3
v infer     0.5.4     v workflows 0.2.2
v modeldata 0.1.0     v yardstick 0.0.7
v parsnip   0.1.5     
-- Conflicts ------------------------------------------------------------- tidymodels_conflicts() --
x scales::discard()     masks purrr::discard()
x magrittr::extract()   masks tidyr::extract()
x plotly::filter()      masks dplyr::filter(), stats::filter()
x recipes::fixed()      masks stringr::fixed()
x dplyr::lag()          masks stats::lag()
x magrittr::set_names() masks purrr::set_names()
x yardstick::spec()     masks readr::spec()
x recipes::step()       masks stats::step()
cd_recipe <- recipe(~., data = cd_tidy) %>%
    update_role(location, new_role = 'id') %>% 
    step_zv(all_numeric()) %>% 
    #step_normalize(all_predictors()) %>% 
    step_umap(all_predictors())

cd_prep <- prep(cd_recipe)

cd_bake <- bake(cd_prep, new_data = NULL)



country_info <- covid_data %>% 
    select(location, continent, population) %>% 
    distinct() %>% 
    arrange(location)
    

cd_final <- cd_bake %>% 
    left_join(country_info, by = 'location')
require(highcharter)
Loading required package: highcharter
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
Highcharts (www.highcharts.com) is a Highsoft software product which is
not free for commercial and Governmental use
withinss <- tibble(
  center = 1:15,
  soq = map_dbl(1:15, ~ kmeans(cd_final %>% select(umap_1, umap_1), centers = .x)$tot.withinss)
)

hchart(withinss, 'line', hcaes(x = center, y = soq))


clusters <- kmeans(cd_final %>% select(umap_1, umap_2), centers = 4)





cd_final %<>% 
    mutate(cluster = paste0('cluster_', clusters$cluster))

cd_final %>% 
    plot_ly(x = ~ umap_1,
            y = ~ umap_2, 
            color = ~ cluster) %>% 
    add_markers(hoverinfo = 'text',
                text = ~ location,
                symbol = ~ continent)

cd_final %>% 
    hchart('scatter',
           hcaes(x = umap_1,
                 y = umap_2,
                 group = continent,
                 color = cluster,
                 size = population / max(population)),
           showInLegend = FALSE) %>% 
    hc_yAxis(
    title = list(text = "y Axis at right"),
    opposite = TRUE,
    alternateGridColor = "#FAFAFA",
    minorTickInterval = "auto",
    minorGridLineDashStyle = "LongDashDotDot",
    showFirstLabel = TRUE,
    showLastLabel = TRUE
      )
NA
NA
NA
flights %>% 
  transmute(week = as.Date(cut(time_hour, "week")), dep_delay, origin) %>% 
  group_by(origin, week) %>%
  summarise(dep_delay = sum(dep_delay, na.rm = TRUE)) %>% 
  e_charts(x = week) %>% 
  e_datazoom(type = 'slider',
             toolbox = FALSE,
             bottom = -5) %>%
  e_tooltip() %>% 
  e_title('Departure delays by airport') %>% 
  e_x_axis(week, axisPointer = list(show = TRUE)) %>% 
  e_line(dep_delay)
`summarise()` has grouped output by 'origin'. You can override using the `.groups` argument.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KYGBge3IgZXZhbD1GQUxTRX0NCmRhdGVzIDwtIHltZCgnMjAyMC0wMS0wMScpICsgd2Vla3MoMDo1MykNCmNvdW50cmllcyA8LSB1bmxpc3QoY291bnRyaWVzX3Blcl9jb250aW5lbnQpICU+JSBzb3J0KCkNCg0KYmFzZV9kZiA8LSB0aWJibGUoDQogICAgZGF0ZSA9IHJlcChkYXRlcywgcmVwKGxlbmd0aChjb3VudHJpZXMpLCBsZW5ndGgoZGF0ZXMpKSksDQogICAgbG9jYXRpb24gPSByZXAoY291bnRyaWVzLCBsZW5ndGgoZGF0ZXMpKQ0KKSAlPiUNCiAgICBmaWx0ZXIoeWVhcihkYXRlKSA9PSAyMDIwKSAlPiUNCiAgICBtdXRhdGUod2VlayA9IHdlZWsoZGF0ZSkpICU+JQ0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbikgJT4lDQogICAgbGVmdF9qb2luKGNvdmlkX2RhdGEgJT4lIHNlbGVjdChsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUgZGlzdGluY3QoKSwNCiAgICAgICAgICAgICAgYnkgPSAnbG9jYXRpb24nKSAlPiUNCiAgICBkcm9wX25hKCkNCg0KZGYgPC0gY292aWRfZGF0YSAlPiUNCiAgICBmaWx0ZXIobHVicmlkYXRlOjp5ZWFyKGRhdGUpID09IDIwMjApICU+JQ0KICAgIHJlcGxhY2VfbmEobGlzdChuZXdfY2FzZXMgPSAwLA0KICAgICAgICAgICAgICAgICAgICBuZXdfZGVhdGhzID0gMCwNCiAgICAgICAgICAgICAgICAgICAgbmV3X3Rlc3RzID0gMCkpICU+JQ0KICAgIGdyb3VwX2J5KHdlZWsgPSB3ZWVrKGRhdGUpLA0KICAgICAgICAgICAgIGxvY2F0aW9uLCBjb250aW5lbnQsIHBvcHVsYXRpb24pICU+JQ0KICAgIHN1bW1hcmlzZShuZXdfY2FzZXMgPSBzdW0obmV3X2Nhc2VzKSwNCiAgICAgICAgICAgICAgcG9zaXRpdmVfcmF0ZSA9IHJvdW5kKHN1bShuZXdfY2FzZXMpIC8gc3VtKG5ld190ZXN0cyksIDIpLA0KICAgICAgICAgICAgICBuZXdfZGVhdGhzID0gc3VtKG5ld19kZWF0aHMpLA0KICAgICAgICAgICAgICAuZ3JvdXBzID0gJ2Ryb3AnKQ0KDQpldm9sdXRpb24gPC0gYmFzZV9kZiAlPiUNCiAgICBsZWZ0X2pvaW4oZGYsIGJ5ID0gYygnd2VlaycsICdsb2NhdGlvbicpKSAlPiUNCiAgICBzZWxlY3Qod2VlaywNCiAgICAgICAgICAgbG9jYXRpb24sDQogICAgICAgICAgIGNvbnRpbmVudCA9IGNvbnRpbmVudC54LA0KICAgICAgICAgICBwb3B1bGF0aW9uID0gcG9wdWxhdGlvbi54LA0KICAgICAgICAgICBuZXdfY2FzZXMsDQogICAgICAgICAgIHBvc2l0aXZlX3JhdGUsDQogICAgICAgICAgIG5ld19kZWF0aHMpICU+JQ0KICAgIHJlcGxhY2VfbmEobGlzdChuZXdfY2FzZXMgPSAwLA0KICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZV9yYXRlID0gMCwNCiAgICAgICAgICAgICAgICAgICAgbmV3X2RlYXRocyA9IDApKSAlPiUNCiAgICBncm91cF9ieShsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUNCiAgICBtdXRhdGUocG9zaXRpdmVfcmF0ZSA9IGlmX2Vsc2UoaXMuaW5maW5pdGUocG9zaXRpdmVfcmF0ZSksIDAsIHBvc2l0aXZlX3JhdGUpLA0KICAgICAgICAgICB0b3RhbF9kZWF0aHMgPSBzbGlkZV9kYmwobmV3X2RlYXRocywgc3VtLCAuYmVmb3JlID0gSW5mLCAuYWZ0ZXIgPSAwLCAuY29tcGxldGUgPSBGQUxTRSksDQogICAgICAgICAgIHRvdGFsX2Nhc2VzID0gc2xpZGVfZGJsKG5ld19jYXNlcywgc3VtLC5iZWZvcmUgPSBJbmYsIC5hZnRlciA9IDAsIC5jb21wbGV0ZSA9IEZBTFNFKSwNCiAgICAgICAgICAgY2FzZXNfcG0gPSByb3VuZCh0b3RhbF9jYXNlcyAvIHBvcHVsYXRpb24gKiAxZSs2KSwNCiAgICAgICAgICAgZGVhdGhzX3BtID0gcm91bmQodG90YWxfZGVhdGhzIC8gcG9wdWxhdGlvbiAqIDFlKzYpKSAlPiUgDQogICAgdW5ncm91cCgpDQoNCg0KDQpldm9sdXRpb24gJT4lDQogICAgcGxvdF9seSh4ICAgICAgICAgPSB+IGRlYXRoc19wbSwNCiAgICAgICAgICAgIHkgICAgICAgICA9IH4gY2FzZXNfcG0sDQogICAgICAgICAgICBjb2xvciAgICAgPSB+IGNvbnRpbmVudCwNCiAgICAgICAgICAgIHNpemUgICAgICA9IH4gcG9wdWxhdGlvbiwNCiAgICAgICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICAgICAgICAgIHRleHQgICAgICA9IH4gbG9jYXRpb24pICU+JQ0KICAgIGFkZF90ZXh0KHggPSA0NSwNCiAgICAgICAgICAgICB5ID0gNTAwLA0KICAgICAgICAgICAgIHRleHQgPSB+IHBhc3RlMCgnd2VlazogJywgd2VlayksDQogICAgICAgICAgICAgZnJhbWUgPSB+IHdlZWssDQogICAgICAgICAgICAgdGV4dGZvbnQgPSBsaXN0KHNpemUgPSAxNTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gdG9SR0IoJ2dyYXk4MCcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gLjUpLA0KICAgICAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkgJT4lDQogICAgYWRkX21hcmtlcnMoZnJhbWUgID0gfiB3ZWVrLA0KICAgICAgICAgICAgICAgIGlkcyAgICA9IH4gbG9jYXRpb24sDQogICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChzaG93bW9kZSA9ICdkaWFtZXRlcicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93cmVmID0gMC45KSkgJT4lDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCh0eXBlID0gJ2xvZycsDQogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMoMCwgMy4yNSksDQogICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICdUb3RhbCBEZWF0aHMgcGVyIE1pbGxpb24nKSwNCiAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1RvdGFsIENhc2VzIHBlciBNaWxsaW9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnbG9nJywNCiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gYygwLCA1LjEpKSwNCiAgICAgICAgICAgdGl0bGUgPSAnVG90YWwgQ2FzZXMgJiBUb3RhbCBEZWF0aHMgcGVyIE1pbGxpb24nKSAlPiUNCiAgICBhbmltYXRpb25fb3B0cyhmcmFtZSAgICAgID0gNTAwLA0KICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24gPSA1MDApICU+JQ0KICAgIGFuaW1hdGlvbl9zbGlkZXIoaGlkZSA9IFRSVUUpDQoNCmBgYA0KDQpgYGB7cn0NCndlZWtfbmV3X2Nhc2VzIDwtIGV2b2x1dGlvbiAlPiUgDQogICAgc2VsZWN0KHdlZWssIGxvY2F0aW9uLCBuZXdfY2FzZXMpICU+JSANCiAgICBtdXRhdGUobmV3X2Nhc2VzX3dlZWsgPSBwYXN0ZTAoJ25ld19jYXNlc193ZWVrXycsIHdlZWspKSAlPiUgDQogICAgc2VsZWN0KC0gd2VlaykgJT4lIA0KICAgIHNwcmVhZChuZXdfY2FzZXNfd2VlaywgbmV3X2Nhc2VzLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCndlZWtfcG9zaXRpdmVfcmF0ZSA8LSBldm9sdXRpb24gJT4lIA0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbiwgcG9zaXRpdmVfcmF0ZSkgJT4lIA0KICAgIG11dGF0ZShwb3NpdGl2ZV9yYXRlX3dlZWsgPSBwYXN0ZTAoJ3Bvc2l0aXZlX3JhdGVfd2Vla18nLCB3ZWVrKSkgJT4lIA0KICAgIHNlbGVjdCgtIHdlZWspICU+JSANCiAgICBzcHJlYWQocG9zaXRpdmVfcmF0ZV93ZWVrLCBwb3NpdGl2ZV9yYXRlLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCndlZWtfbmV3X2RlYXRocyA8LSBldm9sdXRpb24gJT4lIA0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbiwgbmV3X2RlYXRocykgJT4lIA0KICAgIG11dGF0ZShuZXdfZGVhdGhzX3dlZWsgPSBwYXN0ZTAoJ25ld19kZWF0aHNfd2Vla18nLCB3ZWVrKSkgJT4lIA0KICAgIHNlbGVjdCgtIHdlZWspICU+JSANCiAgICBzcHJlYWQobmV3X2RlYXRoc193ZWVrLCBuZXdfZGVhdGhzLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCg0KY2RfdGlkeSA8LSB3ZWVrX25ld19jYXNlcyAlPiUgDQogICAgYmluZF9jb2xzKHdlZWtfcG9zaXRpdmVfcmF0ZSAlPiUgc2VsZWN0KC1sb2NhdGlvbikpICU+JSANCiAgICBiaW5kX2NvbHMod2Vla19uZXdfZGVhdGhzICU+JSBzZWxlY3QoLWxvY2F0aW9uKSkNCg0KY2RfdGlkeQ0KYGBgDQoNCmBgYHtyfQ0KcmVxdWlyZShlbWJlZCkNCnJlcXVpcmUodGlkeW1vZGVscykNCg0KY2RfcmVjaXBlIDwtIHJlY2lwZSh+LiwgZGF0YSA9IGNkX3RpZHkpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKGxvY2F0aW9uLCBuZXdfcm9sZSA9ICdpZCcpICU+JSANCiAgICBzdGVwX3p2KGFsbF9udW1lcmljKCkpICU+JSANCiAgICAjc3RlcF9ub3JtYWxpemUoYWxsX3ByZWRpY3RvcnMoKSkgJT4lIA0KICAgIHN0ZXBfdW1hcChhbGxfcHJlZGljdG9ycygpKQ0KDQpjZF9wcmVwIDwtIHByZXAoY2RfcmVjaXBlKQ0KDQpjZF9iYWtlIDwtIGJha2UoY2RfcHJlcCwgbmV3X2RhdGEgPSBOVUxMKQ0KDQoNCg0KY291bnRyeV9pbmZvIDwtIGNvdmlkX2RhdGEgJT4lIA0KICAgIHNlbGVjdChsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUgDQogICAgZGlzdGluY3QoKSAlPiUgDQogICAgYXJyYW5nZShsb2NhdGlvbikNCiAgICANCg0KY2RfZmluYWwgPC0gY2RfYmFrZSAlPiUgDQogICAgbGVmdF9qb2luKGNvdW50cnlfaW5mbywgYnkgPSAnbG9jYXRpb24nKQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KcmVxdWlyZShoaWdoY2hhcnRlcikNCg0KDQp3aXRoaW5zcyA8LSB0aWJibGUoDQogIGNlbnRlciA9IDE6MTUsDQogIHNvcSA9IG1hcF9kYmwoMToxNSwgfiBrbWVhbnMoY2RfZmluYWwgJT4lIHNlbGVjdCh1bWFwXzEsIHVtYXBfMSksIGNlbnRlcnMgPSAueCkkdG90LndpdGhpbnNzKQ0KKQ0KDQpoY2hhcnQod2l0aGluc3MsICdsaW5lJywgaGNhZXMoeCA9IGNlbnRlciwgeSA9IHNvcSkpDQoNCg0KY2x1c3RlcnMgPC0ga21lYW5zKGNkX2ZpbmFsICU+JSBzZWxlY3QodW1hcF8xLCB1bWFwXzIpLCBjZW50ZXJzID0gNCkNCg0KDQoNCg0KDQpjZF9maW5hbCAlPD4lIA0KICAgIG11dGF0ZShjbHVzdGVyID0gcGFzdGUwKCdjbHVzdGVyXycsIGNsdXN0ZXJzJGNsdXN0ZXIpKQ0KDQpjZF9maW5hbCAlPiUgDQogICAgcGxvdF9seSh4ID0gfiB1bWFwXzEsDQogICAgICAgICAgICB5ID0gfiB1bWFwXzIsIA0KICAgICAgICAgICAgY29sb3IgPSB+IGNsdXN0ZXIpICU+JSANCiAgICBhZGRfbWFya2Vycyhob3ZlcmluZm8gPSAndGV4dCcsDQogICAgICAgICAgICAgICAgdGV4dCA9IH4gbG9jYXRpb24sDQogICAgICAgICAgICAgICAgc3ltYm9sID0gfiBjb250aW5lbnQpDQoNCmNkX2ZpbmFsICU+JSANCiAgICBoY2hhcnQoJ3NjYXR0ZXInLA0KICAgICAgICAgICBoY2Flcyh4ID0gdW1hcF8xLA0KICAgICAgICAgICAgICAgICB5ID0gdW1hcF8yLA0KICAgICAgICAgICAgICAgICBncm91cCA9IGNvbnRpbmVudCwNCiAgICAgICAgICAgICAgICAgY29sb3IgPSBjbHVzdGVyLA0KICAgICAgICAgICAgICAgICBzaXplID0gcG9wdWxhdGlvbiAvIG1heChwb3B1bGF0aW9uKSksDQogICAgICAgICAgIHNob3dJbkxlZ2VuZCA9IEZBTFNFKSAlPiUgDQogICAgaGNfeUF4aXMoDQogICAgdGl0bGUgPSBsaXN0KHRleHQgPSAieSBBeGlzIGF0IHJpZ2h0IiksDQogICAgb3Bwb3NpdGUgPSBUUlVFLA0KICAgIGFsdGVybmF0ZUdyaWRDb2xvciA9ICIjRkFGQUZBIiwNCiAgICBtaW5vclRpY2tJbnRlcnZhbCA9ICJhdXRvIiwNCiAgICBtaW5vckdyaWRMaW5lRGFzaFN0eWxlID0gIkxvbmdEYXNoRG90RG90IiwNCiAgICBzaG93Rmlyc3RMYWJlbCA9IFRSVUUsDQogICAgc2hvd0xhc3RMYWJlbCA9IFRSVUUNCiAgICAgICkNCiAgICAgDQoNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGlyaXMpICsNCiAgICBhZXMoU2VwYWwuTGVuZ3RoLCBTZXBhbC5XaWR0aCwgY29sb3IgPSBTcGVjaWVzKSArDQogICAgZ2VvbV9wb2ludCgpDQoNCmlyaXMgJT4lIA0KICAgIHBsb3RfbHkoeCA9IH4gU2VwYWwuTGVuZ3RoLCB5ID0gfiBTZXBhbC5XaWR0aCwgY29sb3IgPSB+IFNwZWNpZXMpICU+JSANCiAgICBhZGRfbWFya2VycygpDQpgYGANCg0KYGBge3J9DQpwYWNtYW46OnBfbG9hZChlY2hhcnRzNHIpDQplX2NvbW1vbihmb250X2ZhbWlseSA9ICJoZWx2ZXRpY2EiLCB0aGVtZSA9IE5VTEwpDQoNCg0KY2RfZmluYWwgJT4lIA0KICAgIHBsb3RfbHkoeCA9IH4gdW1hcF8xLA0KICAgICAgICAgICAgeSA9IH4gdW1hcF8yLCANCiAgICAgICAgICAgIGNvbG9yID0gfiBjbHVzdGVyKSAlPiUgDQogICAgYWRkX21hcmtlcnMoaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgICAgICAgICAgICAgIHRleHQgPSB+IGxvY2F0aW9uLA0KICAgICAgICAgICAgICAgIHN5bWJvbCA9IH4gY29udGluZW50KQ0KDQpjZF9maW5hbCAlPiUgDQogIGVfY2hhcnQodW1hcF8xKSAlPiUNCiAgZV9zY2F0dGVyKHVtYXBfMiwNCiAgICAgICAgICAgIG5hbWUgPSAnRGltZW50aW9uYWwgUmVkdWN0aW9uJykgJT4lIA0KICBlX2xtKHVtYXBfMiB+IHVtYXBfMSwgbmFtZSA9ICdsaW5lYXIgbW9kZWwnLA0KICAgICAgIGNvbmZpZyA9IGxpc3QoZm9ybXVsYU9uID0gJ2VuZCcsIG1ldGhvZCA9ICdsaW5lYXInKSkgJT4lIA0KICBlX2F4aXNfbGFiZWxzKHggPSAnVU1BUCAxJywgeSA9ICdVTUFQIDInKSAlPiUgDQogIGVfdGl0bGUodGV4dCA9ICdBbmFseXNpcyBvZiBEaW1lbnRpb25hbCBSZWR1Y3Rpb24nLA0KICAgICAgICAgIHN1YnRleHQgPSAnVU1BUCcpICU+JSANCiAgZV94X2F4aXMobmFtZUxvY2F0aW9uID0gJ2NlbnRlcicsDQogICAgICAgICAgIHNwbGl0QXJlYSA9IGxpc3Qoc2hvdyA9IEZBTFNFKSwNCiAgICAgICAgICAgYXhpc0xhYmVsID0gbGlzdChtYXJnaW4gPSAzKSwNCiAgICAgICAgICAgYXhpc1BvaW50ZXIgPSBsaXN0KA0KICAgICAgICAgICAgIHNob3cgPSBUUlVFLA0KICAgICAgICAgICAgIGxpbmVTdHlsZSA9IGxpc3QoDQogICAgICAgICAgICAgICBjb2xvciA9ICcjMDAwMDAwJywNCiAgICAgICAgICAgICAgIHdpZHRoID0gMC43NSwNCiAgICAgICAgICAgICAgIHR5cGUgPSAnZG90dGVkJw0KICAgICAgICAgICAgICkNCiAgICAgICAgICAgKSkgJT4lIA0KICBlX3lfYXhpcyhuYW1lTG9jYXRpb24gPSAnY2VudGVyJywNCiAgICAgICAgICAgc3BsaXRBcmVhID0gbGlzdChzaG93ID0gRkFMU0UpLA0KICAgICAgICAgICBheGlzTGFiZWwgPSBsaXN0KG1hcmdpbiA9IDMpLA0KICAgICAgICAgICBheGlzUG9pbnRlciA9IGxpc3QoDQogICAgICAgICAgICAgc2hvdyA9IFRSVUUsDQogICAgICAgICAgICAgbGluZVN0eWxlID0gbGlzdCgNCiAgICAgICAgICAgICAgIGNvbG9yID0gJyMwMDAwMDAnLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjc1LA0KICAgICAgICAgICAgICAgdHlwZSA9ICdkb3R0ZWQnDQogICAgICAgICAgICAgKQ0KICAgICAgICAgICApKSANCiAgI2VfdG9vbHRpcCgpDQpgYGANCg0KYGBge3J9DQpuX2JpbnMgPC0gMjUNCg0KY2RfZmluYWwgJT4lIA0KICBtdXRhdGUodW1hcF8xX2N1dCA9IGN1dCh1bWFwXzEsIG5fYmlucyksDQogICAgICAgICB1bWFwXzJfY3V0ID0gY3V0KHVtYXBfMiwgbl9iaW5zKSkgJT4lIA0KICBjb3VudCh1bWFwXzFfY3V0LCB1bWFwXzJfY3V0LCBjbHVzdGVyKSAlPiUNCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIA0KICBlX2NoYXJ0KHggPSB1bWFwXzFfY3V0KSAlPiUgDQogIGVfaGVhdG1hcCh1bWFwXzJfY3V0ICxuKSAlPiUgDQogIGVfdmlzdWFsX21hcChuKSAlPiUgDQogIGVfdGl0bGUoJ0hlYXQgbWFwJykNCmBgYA0KDQpgYGB7cn0NCnBhY21hbjo6cF9sb2FkKG55Y2ZsaWdodHMxMykNCmZsaWdodHMgPC0gbnljZmxpZ2h0czEzOjpmbGlnaHRzDQoNCmZsaWdodHMgJT4lIA0KICB0cmFuc211dGUod2VlayA9IGFzLkRhdGUoY3V0KHRpbWVfaG91ciwgIndlZWsiKSksIGRlcF9kZWxheSwgb3JpZ2luKSAlPiUgDQogIGdyb3VwX2J5KG9yaWdpbiwgd2VlaykgJT4lDQogIHN1bW1hcmlzZShkZXBfZGVsYXkgPSBzdW0oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGVfY2hhcnRzKHggPSB3ZWVrKSAlPiUgDQogIGVfZGF0YXpvb20odHlwZSA9ICdzbGlkZXInLA0KICAgICAgICAgICAgIHRvb2xib3ggPSBGQUxTRSwNCiAgICAgICAgICAgICBib3R0b20gPSAtNSkgJT4lDQogIGVfdG9vbHRpcCgpICU+JSANCiAgZV90aXRsZSgnRGVwYXJ0dXJlIGRlbGF5cyBieSBhaXJwb3J0JykgJT4lIA0KICBlX3hfYXhpcyh3ZWVrLCBheGlzUG9pbnRlciA9IGxpc3Qoc2hvdyA9IFRSVUUpKSAlPiUgDQogIGVfbGluZShkZXBfZGVsYXkpDQpgYGANCg0KYGBge3J9DQpteV9zY2FsZSA8LSBmdW5jdGlvbih4KXsNCiAgc2NhbGVzOjpyZXNjYWxlKHgsIHRvID0gYyg1LCAxNSkpDQp9DQoNCmlyaXMgJT4lIA0KICAgIGVfY2hhcnRzKFBldGFsLldpZHRoKSAlPiUgDQogICAgZV9zY2F0dGVyKFBldGFsLkxlbmd0aCwgU2VwYWwuV2lkdGgsIHNjYWxlID0gbXlfc2NhbGUpICU+JSANCiAgICBlX3hfYXhpcyhuYW1lTG9jYXRpb24gPSAnY2VudGVyJywNCiAgICAgICAgICAgc3BsaXRBcmVhID0gbGlzdChzaG93ID0gRkFMU0UpLA0KICAgICAgICAgICBheGlzTGFiZWwgPSBsaXN0KG1hcmdpbiA9IDMpLA0KICAgICAgICAgICBheGlzUG9pbnRlciA9IGxpc3QoDQogICAgICAgICAgICAgc2hvdyA9IFRSVUUsDQogICAgICAgICAgICAgbGluZVN0eWxlID0gbGlzdCgNCiAgICAgICAgICAgICAgIGNvbG9yID0gJyMwMDAwMDAnLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjc1LA0KICAgICAgICAgICAgICAgdHlwZSA9ICdkb3R0ZWQnDQogICAgICAgICAgICAgKQ0KICAgICAgICAgICApKSAlPiUgDQogIGVfeV9heGlzKG5hbWVMb2NhdGlvbiA9ICdjZW50ZXInLA0KICAgICAgICAgICBzcGxpdEFyZWEgPSBsaXN0KHNob3cgPSBGQUxTRSksDQogICAgICAgICAgIGF4aXNMYWJlbCA9IGxpc3QobWFyZ2luID0gMyksDQogICAgICAgICAgIGF4aXNQb2ludGVyID0gbGlzdCgNCiAgICAgICAgICAgICBzaG93ID0gVFJVRSwNCiAgICAgICAgICAgICBsaW5lU3R5bGUgPSBsaXN0KA0KICAgICAgICAgICAgICAgY29sb3IgPSAnIzAwMDAwMCcsDQogICAgICAgICAgICAgICB3aWR0aCA9IDAuNzUsDQogICAgICAgICAgICAgICB0eXBlID0gJ2RvdHRlZCcNCiAgICAgICAgICAgICApDQogICAgICAgICAgICkpICU+JSANCiAgZV90b29sdGlwKCkNCmBgYA0KDQpgYGB7cn0NCmNvdmlkX2RhdGEgJT4lDQogIHNlbGVjdChkYXRlLCBsb2NhdGlvbiwgbmV3X2Nhc2VzKSAlPiUgDQogIGZpbHRlcihsb2NhdGlvbiA9PSAnQ2hpbGUnKSAlPiUNCiAgZmlsdGVyKGx1YnJpZGF0ZTo6eWVhcihkYXRlKSAlaW4lIGMoMjAyMCwgMjAyMSkpICU+JSANCiAgc2VsZWN0KC1sb2NhdGlvbikgJT4lIA0KICBlX2NoYXJ0cyhkYXRlKSAlPiUgDQogIGVfY2FsZW5kYXIocmFuZ2UgPSBjKCcyMDIwLTAzJywgJzIwMjEtMDQnKSkgJT4lIA0KICBlX2hlYXRtYXAobmV3X2Nhc2VzLCBjb29yZF9zeXN0ZW0gPSAnY2FsZW5kYXInKSAlPiUgDQogIGVfdmlzdWFsX21hcChtYXggPSBtYXgoODAwMCkpICU+JSANCiAgZV90b29sdGlwKCkNCmBgYA0KDQpgYGB7cn0NCmNvdmlkX2RhdGEgJT4lDQogIHNlbGVjdChkYXRlLCBsb2NhdGlvbiwgbmV3X2RlYXRocykgJT4lIA0KICBmaWx0ZXIobG9jYXRpb24gPT0gJ0NoaWxlJykgJT4lDQogIGZpbHRlcihsdWJyaWRhdGU6OnllYXIoZGF0ZSkgJWluJSBjKDIwMjAsIDIwMjEpKSAlPiUgDQogIHNlbGVjdCgtbG9jYXRpb24pICU+JSANCiAgZV9jaGFydHMoZGF0ZSkgJT4lIA0KICBlX2NhbGVuZGFyKHJhbmdlID0gYygnMjAyMC0wMycsICcyMDIxLTA0JyksIGRheUxhYmVsID0gbGlzdChmaXJzdERheSA9IDEpKSAlPiUgDQogIGVfaGVhdG1hcChuZXdfZGVhdGhzLCBjb29yZF9zeXN0ZW0gPSAnY2FsZW5kYXInKSAlPiUgDQogIGVfdmlzdWFsX21hcChtYXggPSBtYXgoMjAwKSwNCiAgICAgICAgICAgICAgIHRvcCA9ICdtaWRkbGUnKSAlPiUgDQogIGVfdG9vbHRpcCgpDQpgYGANCg0K